<route lang="json5" type="page">
{
  style: {
    navigationBarTitleText: '磨耳朵',
  },
}
</route>

<template>
  <view class="audio-container">


    <!-- 分类切换按钮组 -->
    <view class="category-tabs">
      <!-- 搜索框 -->
      <view class="search-container">
        <wd-search
          v-model="searchKeyword"
          placeholder="搜索音频名称或绘本集"
          :clearable="true"
          @input="onSearchInput"
          @clear="onSearchClear"
          @search="onSearch"
        />
      </view>

      <!-- 分类按钮组 -->
      <view class="tabs-wrapper">
        <view
          v-for="tab in categoryTabs"
          :key="tab.key"
          class="tab-item"
          :class="{ active: currentCategory === tab.key }"
          @click="switchCategory(tab.key)"
        >
          <text class="tab-text">{{ tab.label }}</text>
        </view>
      </view>
    </view>

    <!-- 音频列表 -->
    <view class="audio-list">
      <!-- 播放全部按钮 -->
      <view class="play-all-btn" @click="playAllAudios" :class="{ disabled: loading || filteredAudioList.length === 0 }">
        <uni-icons type="videocam-filled" size="20" color="#fff"></uni-icons>
        <text class="play-all-text">播放全部</text>
        <text class="audio-count">({{ filteredAudioList.length }})</text>
      </view>

      <!-- 加载状态 -->
      <view v-if="loading" class="loading-container">
        <view class="loading-spinner"></view>
        <text class="loading-text">加载中...</text>
        <text v-if="retryCount > 0" class="retry-text">重试中 ({{ retryCount }}/{{ maxRetryCount }})</text>
      </view>

      <!-- 网络错误状态 -->
      <view v-else-if="networkError && filteredAudioList.length === 0" class="error-container">
        <view class="error-icon">📶</view>
        <text class="error-text">网络连接异常</text>
        <text class="error-tip">请检查网络连接后重试</text>
        <button class="retry-btn" @click="loadAudioData()">重新加载</button>
      </view>

      <!-- 空状态 -->
      <view v-else-if="!loading && !networkError && filteredAudioList.length === 0" class="empty-container">
        <view class="empty-icon">🎵</view>
        <text class="empty-text">暂无音频内容</text>
        <text class="empty-tip">{{ getEmptyTip() }}</text>
      </view>

      <scroll-view v-else class="list-content" scroll-y>
        <view
          v-for="(audio, index) in filteredAudioList"
          :key="audio.id"
          class="audio-item"
          :class="{
            active: currentAudio && currentAudio.id === audio.id,
            loading: currentAudio && currentAudio.id === audio.id && audioLoadingState === 'loading'
          }"
          @click="selectAudio(audio)"
        >
          <view class="item-left">
            <text class="item-number">{{ index + 1 }}</text>
            <image class="item-cover" :src="audio.cover" mode="aspectFill" />
            <view class="item-info">
              <text class="item-title">{{ audio.title }}</text>
              <text class="item-subtitle">{{ audio.subtitle }}</text>
              <!-- 在最近分类中显示具体绘本名称 -->
              <text
                v-if="currentCategory === 'recent' && (audio as any).bookTitle"
                class="item-source-title"
              >
                来自：{{ (audio as any).bookTitle }}
              </text>
              <!-- 加载状态提示 -->
              <text
                v-if="currentAudio && currentAudio.id === audio.id && audioLoadingState === 'loading'"
                class="loading-hint"
              >
                {{ audioLoadingProgress < 50 ? '连接中...' : '加载中...' }} {{ Math.round(audioLoadingProgress) }}%
              </text>
              <text
                v-else-if="currentAudio && currentAudio.id === audio.id && audioLoadingState === 'error'"
                class="error-hint"
              >
                加载失败
              </text>
            </view>
          </view>
          <view class="item-right">
            <view class="item-duration">
              <text class="duration-text">{{ audio.durationText || formatAudioDuration(audio.duration) }}</text>
            </view>
            <!-- 收藏按钮 -->
            <view
              class="favorite-btn"
              @click.stop="toggleFavorite(audio.id)"
            >
              <uni-icons
                :type="audio.isFavorited ? 'heart-filled' : 'heart'"
                size="16"
                :color="audio.isFavorited ? '#ff4757' : '#666'"
              ></uni-icons>
            </view>
            <!-- 删除按钮 -->
            <view
              v-if="currentCategory === 'recent'"
              class="delete-btn"
              @click.stop="removeAudio(audio.id)"
            >
              <uni-icons type="trash" size="16" color="#666"></uni-icons>
            </view>
          </view>
        </view>
      </scroll-view>
    </view>

    <!-- 底部播放器 -->
    <view v-if="currentAudio" class="bottom-player">
      <!-- 音频加载状态提示 -->
      <view v-if="audioLoadingState === 'loading'" class="loading-indicator">
        <view class="loading-bar">
          <view class="loading-progress" :style="{ width: audioLoadingProgress + '%' }"></view>
        </view>
        <text class="loading-text">
          {{ audioLoadingProgress < 30 ? '正在连接服务器...' :
             audioLoadingProgress < 60 ? '正在下载音频...' :
             audioLoadingProgress < 90 ? '即将完成...' : '准备播放...' }}
          {{ Math.round(audioLoadingProgress) }}%
        </text>
      </view>

      <view v-else-if="audioLoadingState === 'error'" class="error-indicator">
        <text class="error-text">{{ audioLoadingError || '音频加载失败' }}</text>
        <view class="retry-btn" @click="retryLoadAudio">
          <text class="retry-text">重试</text>
        </view>
      </view>

      <view class="player-info">
        <image class="player-cover" :src="currentAudio.cover" mode="aspectFill" />
        <view class="player-text">
          <text
            class="player-title"
            :class="{ scrolling: titleNeedsScroll }"
            ref="titleRef"
          >{{ currentAudio.title }}</text>
          <text
            class="player-subtitle"
            :class="{ scrolling: subtitleNeedsScroll }"
            ref="subtitleRef"
          >{{ currentAudio.subtitle }}</text>
          <!-- 显示音频来源信息 -->
          <text
            v-if="(currentAudio as any)?.audioSource === 'reading' && (currentAudio as any)?.bookTitle"
            class="player-source"
          >
            来自：{{ (currentAudio as any).bookTitle }}
          </text>
        </view>
      </view>

      <!-- 播放进度区域 -->
      <view class="player-progress">
        <!-- 时间和进度条 -->
        <view class="progress-container">
          <text class="time-text">{{ formatTime(currentTime) }}</text>
          <view
            class="progress-bar-container"
            @tap="onProgressClick"
            @touchstart="onProgressTouchStart"
            @touchmove="onProgressTouchMove"
            @touchend="onProgressTouchEnd"
          >
            <view class="progress-bar-bg">
              <view
                class="progress-bar-fill"
                :style="{ width: (playProgress * 100) + '%' }"
              ></view>
              <view
                class="progress-bar-thumb"
                :style="{ left: (playProgress * 100) + '%' }"
                v-show="isDragging"
              ></view>
            </view>
          </view>
          <text class="time-text">{{ formatTime(duration) }}</text>
        </view>
      </view>

      <view class="player-controls">
        <view class="control-btn" @click="toggleTimer">
          <text class="iconfont icon-icon-test2" size="20" :color="timerEnabled ? '#007AFF' : '#666'"></text>
        </view>
        <view class="control-btn" @click="togglePlayMode">
          <!-- 根据播放模式显示不同图标，全部显示灰色 -->
          <uni-icons
            v-if="playMode === 'single'"
            type="reload"
            size="20"
            color="#666"
          ></uni-icons>
          <wd-icon
            v-else-if="playMode === 'order'"
            name="backward"
            size="22px"
            color="#666"
          ></wd-icon>
          <wd-icon
            v-else-if="playMode === 'list'"
            name="view-list"
            size="22px"
            color="#666"
          ></wd-icon>
          <wd-icon
            v-else-if="playMode === 'pause'"
            name="stop"
            size="22px"
            color="#666"
          ></wd-icon>
        </view>
        <view class="control-btn" @click="previousTrack">
          <uni-icons type="back" size="20" color="#666"></uni-icons>
        </view>
        <view class="control-btn main-control" @click="togglePlay">
          <wd-icon
            v-if="!isLoading"
            :name="isPlaying ? 'pause' : 'play'"
            size="30px"
            color="#fff"
          ></wd-icon>
          <view v-else class="loading-spinner-small"></view>
        </view>
        <view class="control-btn" @click="nextTrack">
          <uni-icons type="forward" size="20" color="#666"></uni-icons>
        </view>
      </view>
    </view>

    <!-- 定时停止播放弹窗 -->
    <view v-if="showTimerModal" class="timer-modal-overlay" @click="closeTimerModal">
      <view class="timer-modal" @click.stop>
        <view class="modal-header">
          <text class="modal-title">定时停止播放</text>
          <view class="modal-close" @click="closeTimerModal">
            <uni-icons type="close" size="20" color="#666"></uni-icons>
          </view>
        </view>
        <view class="modal-content">
          <view
            v-for="option in timerOptions"
            :key="option.value"
            class="timer-option"
            :class="{ active: audioTimerMinutes === option.value }"
            @click="setTimer(option.value)"
          >
            <text class="option-text">{{ option.label }}</text>
            <view v-if="audioTimerMinutes === option.value" class="option-check">
              <uni-icons type="checkmarkempty" size="16" color="#007AFF"></uni-icons>
            </view>
          </view>

          <!-- 倒计时显示 -->
          <view v-if="audioTimerMinutes > 0 && remainingTime > 0" class="timer-countdown">
            <text class="countdown-text">剩余时间：{{ formatCountdown(remainingTime) }}</text>
          </view>
        </view>
        <view class="modal-footer">
          <button class="modal-btn cancel-btn" @click="cancelTimer">取消定时</button>
          <button class="modal-btn confirm-btn" @click="closeTimerModal">关闭</button>
        </view>
      </view>
    </view>


  </view>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { onLoad, onUnload, onShow, onHide } from '@dcloudio/uni-app'
import {
  getAudioList,
  getRecentPlayAudio,
  getBookSetAudio,
  getBookAudio,
  saveAudioPlayRecord,
  toggleAudioFavorite,
  removeAudioFavorite,
  getFavoriteAudioList,
  deleteAudioPlayRecord,
  formatAudioDuration,
  parseAudioDuration,
  getAudioCoverUrl
} from '@/api/audio'
import { getReadingHistory } from '@/api/record'
import { deleteReadingRecord } from '@/api/reading-records'
import type {
  AudioResourceRespVO,
  AudioCategoryType
} from '@/api/types/audio'

// 时间格式化函数
const formatTime = (seconds: number): string => {
  if (isNaN(seconds) || seconds < 0) return '00:00'

  const minutes = Math.floor(seconds / 60)
  const remainingSeconds = Math.floor(seconds % 60)

  return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`
}

// 进度条相关状态
const isDragging = ref(false)
const dragProgress = ref(0)

// 分类标签
const categoryTabs = ref<Array<{key: AudioCategoryType, label: string, icon?: string}>>([])

// 加载分类数据
function loadCategories() {
  // 使用固定的分类标签
  categoryTabs.value = [
    { key: 'recent', label: '最近' },
    { key: 'chinese', label: '中文' },
    { key: 'english', label: '英文' },
    { key: 'favorite', label: '收藏' }
  ]
}

// 当前分类
const currentCategory = ref<AudioCategoryType>('recent')

// 搜索相关
const searchKeyword = ref('')

// 音频数据
const allAudioList = ref<AudioResourceRespVO[]>([])
const recentAudioList = ref<AudioResourceRespVO[]>([])
const favoriteAudioList = ref<AudioResourceRespVO[]>([])

// 加载状态
const loading = ref(false)
const networkError = ref(false)
const retryCount = ref(0)
const maxRetryCount = 3



// 分页参数
const pageParams = ref({
  pageNo: 1,
  pageSize: 20
})

// 播放状态
const currentAudio = ref<AudioResourceRespVO | null>(null)
const isPlaying = ref(false)
const isLoading = ref(false) // 新增：音频加载状态
const currentTime = ref(0)
const duration = ref(0)
// 播放模式：'single' = 单曲循环, 'order' = 顺序播放, 'list' = 列表循环, 'pause' = 单曲暂停
const playMode = ref<'single' | 'order' | 'list' | 'pause'>('order')
const timerEnabled = ref(false)

// 音频播放器实例
let audioContext: UniApp.InnerAudioContext | null = null

// 音频加载状态
const audioLoadingState = ref<'idle' | 'loading' | 'loaded' | 'error'>('idle')
const audioLoadingProgress = ref(0)
const audioLoadingError = ref('')

// 音频预加载超时时间（毫秒）
const AUDIO_LOAD_TIMEOUT = 60000 // 60秒，给大文件更多时间
const LARGE_FILE_SIZE_THRESHOLD = 10 * 1024 * 1024 // 10MB
const PLAY_START_TIMEOUT = 50000 // 播放启动超时时间：50秒

// 初始化音频播放器
const initAudioContext = () => {
  if (audioContext) {
    audioContext.destroy()
  }

  audioContext = uni.createInnerAudioContext()

  // 优化音频播放器配置以支持大文件
  if (audioContext) {
    // 设置音频播放器属性
    audioContext.autoplay = false // 禁用自动播放，手动控制
    audioContext.startTime = 0    // 从头开始播放

    // 在支持的平台上启用更好的缓冲策略
    try {
      // 这些属性在某些平台可能不支持，用try-catch包裹
      if ('preload' in audioContext) {
        (audioContext as any).preload = 'auto'
      }
      if ('volume' in audioContext) {
        (audioContext as any).volume = 1.0
      }
    } catch (error) {
      console.warn('设置音频播放器高级属性失败:', error)
    }
  }

  // 监听音频播放事件
  audioContext.onPlay(() => {
    console.log('音频真正开始播放')
    isPlaying.value = true
    isLoading.value = false // 播放开始，停止加载状态
    audioLoadingState.value = 'loaded'
  })

  // 监听音频暂停事件
  audioContext.onPause(() => {
    console.log('音频暂停')
    isPlaying.value = false
    isLoading.value = false
  })

  // 监听音频停止事件
  audioContext.onStop(() => {
    console.log('音频停止')
    isPlaying.value = false
    isLoading.value = false
  })

  // 监听音频播放完成事件
  audioContext.onEnded(() => {
    console.log('音频播放完成')
    isPlaying.value = false
    isLoading.value = false
    onAudioComplete()
  })

  // 监听音频播放错误事件
  audioContext.onError((error) => {
    console.error('音频播放错误:', error)
    audioLoadingState.value = 'error'
    isPlaying.value = false
    isLoading.value = false // 错误时停止加载状态

    // 延迟显示错误，给音频更多加载时间
    setTimeout(() => {
      if (audioLoadingState.value === 'error') {
        handleAudioError(error)
      }
    }, 2000) // 延迟2秒显示错误
  })

  // 监听音频加载完成事件
  audioContext.onCanplay(() => {
    console.log('音频可以播放了')
    audioLoadingState.value = 'loaded'
    audioLoadingProgress.value = 100

    // 更新音频总时长
    if (audioContext?.duration) {
      duration.value = Math.floor(audioContext.duration)
    }
  })

  // 监听音频等待数据事件
  audioContext.onWaiting(() => {
    console.log('音频等待数据中...')
    audioLoadingState.value = 'loading'
  })

  // 监听音频时间更新事件
  audioContext.onTimeUpdate(() => {
    if (audioContext && currentAudio.value && isPlaying.value) {
      const newCurrentTime = Math.floor(audioContext.currentTime)
      const audioContextPaused = audioContext.paused

      // 检查播放状态是否同步
      if (isPlaying.value !== !audioContextPaused) {
        // 同步播放状态
        isPlaying.value = !audioContextPaused
      }

      if (newCurrentTime !== currentTime.value && newCurrentTime >= 0) {
        currentTime.value = newCurrentTime
        // totalPlayTime 应该是累计播放时长，不是当前时间
        // 这里我们使用当前时间作为总播放时长的基础
        totalPlayTime.value = newCurrentTime

        // 每30秒保存一次播放记录，减少API调用频率
        if (newCurrentTime > 0 && newCurrentTime % 30 === 0) {
          saveCurrentPlayRecord()
        }

        // 检查是否播放完成
        if (newCurrentTime >= duration.value && duration.value > 0) {
          onAudioComplete()
        }
      }
    }
  })
}

// 播放记录相关
const playStartTime = ref(0) // 播放开始时间
const totalPlayTime = ref(0) // 总播放时长
let playProgressTimer: any = null

// 音频错误处理函数
const handleAudioError = (error: any) => {
  console.error('音频播放错误详情:', error)

  let errorMessage = '音频播放失败'
  let showRetry = true

  // 根据错误类型提供不同的提示
  if (error && error.errMsg) {
    const errMsg = error.errMsg.toLowerCase()

    if (errMsg.includes('network') || errMsg.includes('timeout')) {
      errorMessage = '网络连接不稳定，建议在WiFi环境下播放大文件'
    } else if (errMsg.includes('format') || errMsg.includes('decode')) {
      errorMessage = '音频格式不支持或文件损坏'
      showRetry = false
    } else if (errMsg.includes('permission')) {
      errorMessage = '没有音频播放权限'
      showRetry = false
    } else if (errMsg.includes('memory') || errMsg.includes('resource')) {
      errorMessage = '音频文件过大，建议清理设备存储空间后重试'
    } else if (errMsg.includes('url') || errMsg.includes('src')) {
      errorMessage = '音频地址无效或服务器暂时不可用'
    }
  }

  audioLoadingError.value = errorMessage

  if (showRetry) {
    uni.showModal({
      title: '播放遇到问题',
      content: errorMessage + '\n\n是否重新尝试播放？',
      showCancel: true,
      cancelText: '取消',
      confirmText: '重试',
      success: (res) => {
        if (res.confirm && currentAudio.value) {
          // 重置状态后重试
          audioLoadingState.value = 'idle'
          audioLoadingError.value = ''
          setTimeout(() => {
            playAudio(currentAudio.value!)
          }, 1000) // 延迟1秒重试
        }
      }
    })
  } else {
    uni.showToast({
      title: errorMessage,
      icon: 'none',
      duration: 4000
    })
  }
}

// 检查音频文件大小
const checkAudioFileSize = async (audioUrl: string): Promise<{ size: number; isLarge: boolean }> => {
  try {
    // 通过HEAD请求获取文件大小
    const response = await uni.request({
      url: audioUrl,
      method: 'HEAD'
    })

    const contentLength = response.header['content-length'] || response.header['Content-Length']
    const fileSize = contentLength ? parseInt(contentLength) : 0

    return {
      size: fileSize,
      isLarge: fileSize > LARGE_FILE_SIZE_THRESHOLD
    }
  } catch (error) {
    console.warn('无法获取音频文件大小:', error)
    return { size: 0, isLarge: false }
  }
}

// 预加载音频
const preloadAudio = (audioUrl: string): Promise<boolean> => {
  return new Promise((resolve) => {
    audioLoadingState.value = 'loading'
    audioLoadingProgress.value = 0

    const testAudio = uni.createInnerAudioContext()
    let loadTimeout: any = null
    let progressInterval: any = null
    let errorTimeout: any = null

    // 设置加载超时
    loadTimeout = setTimeout(() => {
      console.warn('音频预加载超时，但继续尝试播放')
      clearInterval(progressInterval)
      clearTimeout(errorTimeout)
      testAudio.destroy()

      // 超时不直接失败，而是继续尝试播放
      audioLoadingState.value = 'loaded'
      audioLoadingProgress.value = 100
      audioLoadingError.value = '文件较大，正在后台加载...'
      resolve(true)
    }, AUDIO_LOAD_TIMEOUT)

    // 模拟加载进度，前期较快，后期较慢
    progressInterval = setInterval(() => {
      if (audioLoadingProgress.value < 70) {
        audioLoadingProgress.value += Math.random() * 8 + 2
      } else if (audioLoadingProgress.value < 90) {
        audioLoadingProgress.value += Math.random() * 3 + 1
      } else if (audioLoadingProgress.value < 95) {
        audioLoadingProgress.value += Math.random() * 1
      }
    }, 300)

    testAudio.onCanplay(() => {
      console.log('音频预加载成功')
      clearTimeout(loadTimeout)
      clearTimeout(errorTimeout)
      clearInterval(progressInterval)
      audioLoadingState.value = 'loaded'
      audioLoadingProgress.value = 100
      audioLoadingError.value = ''
      testAudio.destroy()
      resolve(true)
    })

    testAudio.onError((error) => {
      console.error('音频预加载失败:', error)

      // 延迟处理错误，给音频更多时间
      errorTimeout = setTimeout(() => {
        clearTimeout(loadTimeout)
        clearInterval(progressInterval)
        audioLoadingState.value = 'error'
        audioLoadingError.value = '音频加载失败，请检查网络连接'
        testAudio.destroy()
        resolve(false)
      }, 3000) // 延迟3秒处理错误
    })

    testAudio.src = audioUrl
  })
}

// 状态同步检查定时器
let statusSyncTimer: any = null

// 开始状态同步检查
const startStatusSyncCheck = () => {
  if (statusSyncTimer) {
    clearInterval(statusSyncTimer)
  }

  statusSyncTimer = setInterval(() => {
    if (audioContext && currentAudio.value) {
      const audioContextPlaying = !audioContext.paused

      if (isPlaying.value !== audioContextPlaying) {
        // 同步状态
        isPlaying.value = audioContextPlaying
      }
    }
  }, 1000) // 每秒检查一次
}

// 停止状态同步检查
const stopStatusSyncCheck = () => {
  if (statusSyncTimer) {
    clearInterval(statusSyncTimer)
    statusSyncTimer = null
  }
}

// 进度条交互函数
const onProgressClick = (event: any) => {
  if (!currentAudio.value || !audioContext) return

  // 使用uni-app的方式获取点击位置
  uni.createSelectorQuery().select('.progress-bar-container').boundingClientRect((rect: any) => {
    if (rect) {
      // uni-app tap事件的坐标获取方式
      const clickX = (event.detail?.x || event.touches?.[0]?.clientX || 0) - rect.left
      const progressWidth = rect.width
      const clickProgress = Math.max(0, Math.min(1, clickX / progressWidth))

      const targetTime = clickProgress * duration.value
      seekToTime(targetTime)
    }
  }).exec()
}

const onProgressTouchStart = (event: any) => {
  if (!currentAudio.value || !audioContext) return

  isDragging.value = true
  updateDragProgress(event)
}

const onProgressTouchMove = (event: any) => {
  if (!isDragging.value) return

  event.preventDefault()
  updateDragProgress(event)
}

const onProgressTouchEnd = () => {
  if (!isDragging.value) return

  const targetTime = dragProgress.value * duration.value
  seekToTime(targetTime)
  isDragging.value = false
}

const updateDragProgress = (event: any) => {
  uni.createSelectorQuery().select('.progress-bar-container').boundingClientRect((rect: any) => {
    if (rect && event.touches && event.touches[0]) {
      const touchX = event.touches[0].clientX - rect.left
      const progressWidth = rect.width
      const progress = Math.max(0, Math.min(1, touchX / progressWidth))

      dragProgress.value = progress
    }
  }).exec()
}

const seekToTime = (targetTime: number) => {
  if (!audioContext || !currentAudio.value) return

  try {
    audioContext.seek(targetTime)
    // 不要手动设置时间，让onTimeUpdate事件来更新
    // 这样避免了时间冲突

    // 保存播放记录
    setTimeout(() => {
      saveCurrentPlayRecord()
    }, 100) // 延迟一下，等待时间更新
  } catch (error) {
    console.error('跳转播放位置失败:', error)
  }
}

// 计算当前播放进度百分比
const playProgress = computed(() => {
  if (isDragging.value) {
    return dragProgress.value
  }

  if (duration.value <= 0) return 0

  // 使用Math.floor确保进度值稳定，避免小数点导致的抖动
  const progress = Math.floor(currentTime.value) / Math.floor(duration.value)
  return Math.max(0, Math.min(1, progress))
})

// 获取当前播放模式的显示名称
const playModeName = computed(() => {
  const modeNames = {
    order: '顺序播放',
    list: '列表循环',
    single: '单曲循环',
    pause: '单曲暂停'
  }
  return modeNames[playMode.value]
})

// 文本滚动状态
const titleNeedsScroll = ref(false)
const subtitleNeedsScroll = ref(false)

// 定时器相关
const showTimerModal = ref(false)
const audioTimerMinutes = ref(0) // 当前设置的定时分钟数
const remainingTime = ref(0) // 剩余时间（秒）
const timerInterval = ref(null) // 定时器引用

// 定时器选项
const timerOptions = ref([
  { value: 0, label: '不启用' },
  { value: 15, label: '15分钟' },
  { value: 30, label: '30分钟' },
  { value: 60, label: '60分钟' },
  { value: 90, label: '90分钟' }
])

// 筛选后的音频列表
const filteredAudioList = computed(() => {
  // 首先根据分类筛选
  let audioList: AudioResourceRespVO[] = []

  switch (currentCategory.value) {
    case 'recent':
      audioList = recentAudioList.value
      break
    case 'english':
      audioList = allAudioList.value.filter(audio => {
        const audioLang = audio.language as string
        const audioCategory = audio.category as string
        return audioLang === 'en' || audioCategory === 'english'
      })
      break
    case 'chinese':
      audioList = allAudioList.value.filter(audio => {
        const audioLang = audio.language as string
        const audioCategory = audio.category as string
        return audioLang === 'zh' || audioCategory === 'chinese'
      })
      break
    case 'favorite':
      audioList = favoriteAudioList.value
      break
    default:
      audioList = allAudioList.value
      break
  }

  // 如果有搜索关键词，进行搜索过滤
  if (searchKeyword.value.trim()) {
    const keyword = searchKeyword.value.trim().toLowerCase()
    audioList = audioList.filter(audio => {
      // 搜索音频标题
      const titleMatch = audio.title.toLowerCase().includes(keyword)
      // 搜索音频副标题
      const subtitleMatch = audio.subtitle?.toLowerCase().includes(keyword) || false
      // 注意：由于AudioResourceRespVO没有bookSetTitle字段，暂时只搜索title和subtitle
      // 如果需要搜索绘本集名称，需要从其他地方获取或修改API

      return titleMatch || subtitleMatch
    })
  }

  return audioList
})

// 数据加载函数
async function loadAudioData(showLoading = true, isRetry = false) {
  if (loading.value) {
    return
  }

  if (showLoading) {
    loading.value = true
    networkError.value = false
  }

  try {
    // 检查网络状态
    const networkInfo = await uni.getNetworkType()

    if (networkInfo.networkType === 'none') {
      throw new Error('网络连接不可用')
    }

    switch (currentCategory.value) {
      case 'recent':
        await loadRecentAudio()
        break
      case 'favorite':
        await loadFavoriteAudio()
        break
      case 'english':
      case 'chinese':
        await loadAudioByLanguage(currentCategory.value)
        break
      default:
        await loadAllAudio()
        break
    }

    // 加载成功，重置重试计数
    retryCount.value = 0
    networkError.value = false
  } catch (error) {
    console.error('加载音频数据失败:', error)
    networkError.value = true

    if (!isRetry && retryCount.value < maxRetryCount) {
      retryCount.value++

      // 延迟重试，延迟时间递增
      setTimeout(() => {
        loadAudioData(false, true)
      }, retryCount.value * 1000)
    } else {
      handleLoadError(error)
    }
  } finally {
    if (showLoading) {
      loading.value = false
    }
  }
}

// 处理加载错误
function handleLoadError(error: any) {
  let errorMessage = '加载失败，请重试'
  let showRetryButton = true

  // 根据错误类型显示不同的提示
  if (error?.message?.includes('网络连接不可用') || error?.message?.includes('Network')) {
    errorMessage = '网络连接不可用，请检查网络设置后重试'
  } else if (error?.message?.includes('timeout')) {
    errorMessage = '请求超时，请检查网络连接后重试'
  } else if (error?.code === 401) {
    errorMessage = '登录已过期，请重新登录'
    showRetryButton = false
  } else if (error?.code === 403) {
    errorMessage = '没有访问权限，请联系管理员'
    showRetryButton = false
  } else if (error?.code >= 500) {
    errorMessage = '服务器暂时不可用，请稍后重试'
  } else if (retryCount.value >= maxRetryCount) {
    errorMessage = `已重试${maxRetryCount}次仍然失败，请检查网络连接或稍后再试`
  }

  // 显示错误提示
  if (showRetryButton) {
    uni.showModal({
      title: '加载失败',
      content: errorMessage,
      showCancel: true,
      cancelText: '取消',
      confirmText: '重试',
      success: (res) => {
        if (res.confirm) {
          // 重置重试计数并重新加载
          retryCount.value = 0
          setTimeout(() => {
            loadAudioData()
          }, 500)
        }
      }
    })
  } else {
    uni.showToast({
      title: errorMessage,
      icon: 'none',
      duration: 3000
    })
  }
}

// 加载全部音频
async function loadAllAudio() {
  const params = {
    category: 'all',
    limit: pageParams.value.pageSize
  }

  const response = await getAudioList(params)

  if (response.code === 0 && response.data) {
    const audioList = Array.isArray(response.data) ? response.data : []
    allAudioList.value = audioList.map(formatAudioItem)
  }
}

// 加载最近播放音频 - 合并最近阅读绘本音频和主动播放音频记录
async function loadRecentAudio() {
  try {
    // 并行获取两种数据源
    const [recentReadingAudios, recentPlayAudios] = await Promise.all([
      loadRecentReadingAudios(),
      loadRecentPlayAudios()
    ])

    // 合并两种音频数据
    const allAudios = [...recentReadingAudios, ...recentPlayAudios]

    // 去重（基于音频ID）
    const uniqueAudios = allAudios.reduce((acc, audio) => {
      if (!acc.find((item: any) => item.id === audio.id)) {
        acc.push(audio)
      }
      return acc
    }, [] as any[])

    // 按时间排序（最近的在前）
    uniqueAudios.sort((a: any, b: any) => {
      // 优先使用lastPlayAt（主动播放时间），其次使用lastReadAt（阅读时间）
      const timeA = new Date(a.lastPlayAt || a.lastReadAt || 0).getTime()
      const timeB = new Date(b.lastPlayAt || b.lastReadAt || 0).getTime()
      return timeB - timeA
    })

    // 限制数量并格式化
    const limitedAudios = uniqueAudios.slice(0, 50)
    recentAudioList.value = limitedAudios.map(formatAudioItem)

    console.log(`合并获取到 ${recentAudioList.value.length} 个最近音频（阅读相关: ${recentReadingAudios.length}, 播放记录: ${recentPlayAudios.length}）`)
  } catch (error) {
    console.error('加载最近音频失败:', error)
    recentAudioList.value = []
  }
}

// 获取最近阅读绘本的音频
async function loadRecentReadingAudios() {
  try {
    // 1. 获取阅读历史记录
    const readingHistoryResponse = await getReadingHistory({
      page: 1,
      size: 15
    })

    console.log('阅读历史接口完整响应:', readingHistoryResponse)

    if (readingHistoryResponse.code !== 0 || !readingHistoryResponse.data) {
      console.warn('获取阅读历史记录失败:', readingHistoryResponse.msg)
      return []
    }

    // 检查数据结构
    console.log('阅读历史数据结构:', readingHistoryResponse.data)

    // 后端直接返回数组，不是分页结构
    const recentReadings = readingHistoryResponse.data
    console.log('获取到的阅读历史记录:', recentReadings)

    if (!Array.isArray(recentReadings) || recentReadings.length === 0) {
      console.log('没有阅读历史记录')
      return []
    }

    // 2. 为每个阅读记录获取对应绘本的音频
    const audioPromises = recentReadings.map(async (reading: any) => {
      try {
        console.log('处理阅读记录:', {
          id: reading.id,
          bookId: reading.bookId,
          bookTitle: reading.bookTitle,
          bookSetId: reading.bookSetId,
          bookSetTitle: reading.bookSetTitle
        })

        // 如果有具体的绘本ID，优先获取绘本音频
        if (reading.bookId) {
          console.log(`尝试获取绘本 ${reading.bookId} 的音频`)
          const audioResponse = await getBookAudio(reading.bookId)
          console.log(`绘本 ${reading.bookId} 音频响应:`, audioResponse)

          if (audioResponse.code === 0 && audioResponse.data) {
            const audios = Array.isArray(audioResponse.data) ? audioResponse.data : []
            console.log(`绘本 ${reading.bookId} 找到 ${audios.length} 个音频`, audios)

            if (audios.length > 0) {
              return audios.map((audio: any) => ({
                ...audio,
                bookTitle: reading.bookTitle,
                bookSetTitle: reading.bookSetTitle,
                bookId: reading.bookId,
                bookSetId: reading.bookSetId,
                readingRecordId: reading.id, // 保存阅读记录ID，用于删除
                lastReadAt: reading.lastReadAt,
                audioSource: 'reading', // 标记音频来源
                // 如果音频没有封面，使用绘本封面
                cover: audio.cover || reading.bookCover
              }))
            }
          } else {
            console.log(`绘本 ${reading.bookId} 音频获取失败:`, audioResponse.msg)
          }
        }

        // 如果没有具体绘本ID或绘本音频获取失败，尝试获取绘本集音频
        if (reading.bookSetId) {
          console.log(`尝试获取绘本集 ${reading.bookSetId} 的音频`)
          const audioResponse = await getBookSetAudio(reading.bookSetId)
          console.log(`绘本集 ${reading.bookSetId} 音频响应:`, audioResponse)

          if (audioResponse.code === 0 && audioResponse.data) {
            const audios = Array.isArray(audioResponse.data) ? audioResponse.data : []
            console.log(`绘本集 ${reading.bookSetId} 找到 ${audios.length} 个音频`, audios)

            if (audios.length > 0) {
              return audios.map((audio: any) => ({
                ...audio,
                bookSetTitle: reading.bookSetTitle,
                bookSetId: reading.bookSetId,
                readingRecordId: reading.id, // 保存阅读记录ID，用于删除
                lastReadAt: reading.lastReadAt,
                audioSource: 'reading', // 标记音频来源
                // 如果音频没有封面，使用绘本封面
                cover: audio.cover || reading.bookCover
              }))
            }
          } else {
            console.log(`绘本集 ${reading.bookSetId} 音频获取失败:`, audioResponse.msg)
          }
        }

        return []
      } catch (error) {
        console.warn(`获取阅读记录 ${reading.bookId || reading.bookSetId} 的音频失败:`, error)
        return []
      }
    })

    // 3. 等待所有音频获取完成并合并
    const audioArrays = await Promise.all(audioPromises)
    return audioArrays.flat()
  } catch (error) {
    console.error('获取最近阅读绘本音频失败:', error)
    return []
  }
}

// 获取最近主动播放的音频记录
async function loadRecentPlayAudios() {
  try {
    const params = { limit: 30 }
    const response = await getRecentPlayAudio(params)

    if (response.code === 0 && response.data) {
      const audioList = Array.isArray(response.data) ? response.data : []
      // 为播放记录音频添加标记
      return audioList.map((audio: any) => ({
        ...audio,
        audioSource: 'play', // 标记音频来源
        lastPlayAt: audio.lastPlayAt || audio.updateTime || audio.createTime
      }))
    }
    return []
  } catch (error) {
    console.error('获取最近播放音频失败:', error)
    return []
  }
}

// 加载收藏音频
async function loadFavoriteAudio() {
  const params = {
    page: pageParams.value.pageNo,
    size: pageParams.value.pageSize
  }

  const response = await getFavoriteAudioList(params)

  if (response.code === 0 && response.data) {
    // 后端返回的是分页结果，需要提取list并转换格式
    const favoriteItems = (response.data as any).list || []

    // 将FavoriteItemRespVO转换为AudioResourceRespVO格式
    favoriteAudioList.value = favoriteItems.map(convertFavoriteToAudio)
  }
}

// 按语言加载音频
async function loadAudioByLanguage(language: string) {
  // 将分类名称转换为对应的语言代码
  const langCode = language === 'chinese' ? 'zh' : language === 'english' ? 'en' : language

  const params = {
    category: language,  // 分类使用原始值：chinese/english
    lang: langCode,      // 语言代码使用转换后的值：zh/en
    limit: pageParams.value.pageSize
  }

  const response = await getAudioList(params)

  if (response.code === 0 && response.data) {
    const audioList = Array.isArray(response.data) ? response.data : []
    allAudioList.value = audioList.map(formatAudioItem)
  }
}

// 格式化音频数据
function formatAudioItem(audio: AudioResourceRespVO) {
  return {
    ...audio,
    durationText: formatAudioDuration(audio.duration),
    cover: getAudioCoverUrl(audio)
  }
}

// 将收藏项转换为音频格式
function convertFavoriteToAudio(favoriteItem: any): AudioResourceRespVO {
  // 尝试从不同字段获取音频URL
  const audioUrl = favoriteItem.audioUrl || favoriteItem.resourceUrl || favoriteItem.url || ''

  return {
    id: favoriteItem.id,
    title: favoriteItem.title,
    subtitle: favoriteItem.description || '',
    audioUrl: audioUrl,
    cover: favoriteItem.cover || '',
    duration: favoriteItem.duration || 0,
    durationText: formatAudioDuration(favoriteItem.duration || 0),
    category: 'favorite',
    language: favoriteItem.language || 'en',
    bookId: undefined,
    bookSetId: undefined,
    sortOrder: 0,
    enabled: true,
    playCount: 0,
    likeCount: 0,
    isLiked: false,
    isFavorited: true, // 收藏列表中的都是已收藏的
    playStatus: {
      playProgress: 0,
      isCompleted: false,
      playCount: 0,
      lastPlayAt: undefined
    },
    createTime: favoriteItem.favoriteTime,
    updateTime: favoriteItem.favoriteTime
  }
}

// 切换分类
function switchCategory(category: AudioCategoryType) {
  currentCategory.value = category
  // 切换分类时清空搜索关键词
  searchKeyword.value = ''
  loadAudioData()
}

// 搜索相关函数
function onSearchInput(value: string) {
  searchKeyword.value = value
  // 实时搜索，无需额外处理，computed会自动更新
}

function onSearchClear() {
  searchKeyword.value = ''
  // 清空搜索时显示提示
  if (filteredAudioList.value.length === 0) {
    uni.showToast({
      title: '已清空搜索',
      icon: 'none',
      duration: 1500
    })
  }
}

function onSearch(value: string) {
  searchKeyword.value = value
  // 搜索时显示结果提示
  if (value.trim()) {
    const resultCount = filteredAudioList.value.length
    uni.showToast({
      title: `找到 ${resultCount} 个结果`,
      icon: 'none',
      duration: 1500
    })
  }
}



// 获取空状态提示文本
function getEmptyTip(): string {
  // 如果有搜索关键词，显示搜索结果为空的提示
  if (searchKeyword.value.trim()) {
    return `未找到包含"${searchKeyword.value}"的音频，试试其他关键词吧`
  }

  // 根据分类显示不同的空状态提示
  switch (currentCategory.value) {
    case 'recent':
      return '还没有最近音频记录，快去阅读绘本或播放音频吧~'
    case 'favorite':
      return '还没有收藏音频，点击❤️收藏喜欢的音频'
    case 'english':
      return '暂无英文音频内容'
    case 'chinese':
      return '暂无中文音频内容'
    default:
      return '暂无音频内容，请稍后再试'
  }
}

// 播放全部音频
function playAllAudios() {
  if (loading.value) {
    uni.showToast({
      title: '正在加载中，请稍候',
      icon: 'none'
    })
    return
  }

  if (filteredAudioList.value.length === 0) {
    uni.showToast({
      title: '暂无可播放的音频',
      icon: 'none'
    })
    return
  }

  const firstAudio = filteredAudioList.value[0]
  // 先选择音频，然后开始播放
  selectAudio(firstAudio)
  // 延迟一下确保音频加载完成
  setTimeout(() => {
    if (currentAudio.value) {
      playAudio(currentAudio.value)
    }
  }, 100)

  uni.showToast({
    title: `开始播放全部`,
    icon: 'success'
  })
}

// 播放/暂停
function togglePlay() {
  if (!currentAudio.value) {
    return
  }

  // 如果正在加载中，不响应点击
  if (isLoading.value) {
    uni.showToast({
      title: '音频加载中，请稍候...',
      icon: 'none',
      duration: 1500
    })
    return
  }

  if (!audioContext) {
    // 重新播放当前音频
    playAudio(currentAudio.value)
    return
  }

  const previousState = isPlaying.value

  try {
    if (previousState) {
      // 当前正在播放，需要暂停
      audioContext.pause()

      // 手动设置播放状态为false（防止事件监听延迟）
      isPlaying.value = false

      // 暂停播放，保存当前记录
      saveCurrentPlayRecord()

      if (playProgressTimer) {
        clearInterval(playProgressTimer)
        playProgressTimer = null
      }

    } else {
      // 当前暂停，需要播放
      // 设置加载状态
      isLoading.value = true

      audioContext.play()

      // 不要立即设置播放状态，等待onPlay事件
      // isPlaying.value = true

      // 记录播放开始时间
      playStartTime.value = Date.now()

      startPlayProgressTracking()
      startStatusSyncCheck()

      // 设置超时，如果50秒内没有开始播放，停止加载状态
      setTimeout(() => {
        if (isLoading.value && !isPlaying.value) {
          isLoading.value = false
          uni.showToast({
            title: '播放启动超时，请检查网络或重试',
            icon: 'none',
            duration: 3000
          })
        }
      }, 50000) // 50秒超时
    }
  } catch (error) {
    // 恢复之前的播放状态
    isPlaying.value = previousState
    isLoading.value = false

    uni.showToast({
      title: '播放控制失败',
      icon: 'none'
    })
  }
}

// 选择音频（不自动播放）
async function selectAudio(audio: AudioResourceRespVO) {
  // 检查音频URL是否存在
  if (!audio.audioUrl) {
    uni.showToast({
      title: '音频地址无效',
      icon: 'none'
    })
    return
  }

  // 如果有正在播放的音频，先保存播放记录
  if (currentAudio.value && isPlaying.value) {
    saveCurrentPlayRecord()
    // 停止当前播放
    if (audioContext) {
      audioContext.pause()
      isPlaying.value = false
    }
  }

  // 初始化音频播放器
  if (!audioContext) {
    initAudioContext()
  }

  // 设置当前音频信息
  currentAudio.value = audio
  currentTime.value = 0
  duration.value = parseAudioDuration(audio.durationText || formatAudioDuration(audio.duration))

  // 重置进度条状态
  isDragging.value = false
  dragProgress.value = 0

  // 重置播放状态
  isPlaying.value = false
  isLoading.value = false
  playStartTime.value = 0
  totalPlayTime.value = 0

  // 重置加载状态
  audioLoadingState.value = 'idle'
  audioLoadingProgress.value = 0
  audioLoadingError.value = ''

  // 检查文件大小并给出提示
  try {
    const fileSizeInfo = await checkAudioFileSize(audio.audioUrl)
    if (fileSizeInfo.isLarge) {
      const fileSizeMB = (fileSizeInfo.size / 1024 / 1024).toFixed(1)
      uni.showModal({
        title: '大文件提醒',
        content: `音频文件大小约为 ${fileSizeMB}MB，建议在WiFi环境下播放。\n\n加载时间可能较长，请耐心等待。`,
        showCancel: true,
        cancelText: '取消',
        confirmText: '继续播放',
        success: (res) => {
          if (res.confirm) {
            // 显示友好的加载提示
            uni.showToast({
              title: `正在加载${fileSizeMB}MB音频，请稍候...`,
              icon: 'none',
              duration: 3000
            })
            loadAudioWithPreload(audio)
          } else {
            // 用户取消，清除当前音频
            currentAudio.value = null
          }
        }
      })
      return
    }
  } catch (error) {
    console.warn('检查文件大小失败，继续播放:', error)
  }

  // 设置音频源但不播放
  try {
    audioContext!.src = audio.audioUrl
    audioContext!.loop = playMode.value === 'single' // 只有单曲循环模式才启用loop

    // 检查文本是否需要滚动
    checkTextScrolling()
  } catch (error) {
    console.error('音频加载失败:', error)
    handleAudioError(error)
  }
}

// 使用预加载机制加载音频
async function loadAudioWithPreload(audio: AudioResourceRespVO) {
  try {
    // 显示加载提示
    uni.showLoading({
      title: '音频加载中...',
      mask: true
    })

    // 预加载音频
    const preloadSuccess = await preloadAudio(audio.audioUrl)

    uni.hideLoading()

    if (preloadSuccess) {
      // 预加载成功，设置音频源
      audioContext!.src = audio.audioUrl
      audioContext!.loop = playMode.value === 'single' // 只有单曲循环模式才启用loop
      checkTextScrolling()

      uni.showToast({
        title: '音频加载完成',
        icon: 'success',
        duration: 1500
      })
    } else {
      // 预加载失败，显示错误信息
      uni.showToast({
        title: audioLoadingError.value || '音频加载失败',
        icon: 'none',
        duration: 3000
      })
      currentAudio.value = null
    }
  } catch (error) {
    uni.hideLoading()
    console.error('预加载音频失败:', error)
    handleAudioError(error)
    currentAudio.value = null
  }
}

// 重试加载音频
function retryLoadAudio() {
  if (currentAudio.value) {
    console.log('重试加载音频:', currentAudio.value.title)
    loadAudioWithPreload(currentAudio.value)
  }
}

// 播放指定音频
async function playAudio(audio: AudioResourceRespVO) {
  // 如果传入的音频与当前音频不同，先选择音频
  if (!currentAudio.value || currentAudio.value.id !== audio.id) {
    await selectAudio(audio)

    // 等待选择完成，如果选择失败则返回
    if (!currentAudio.value) {
      return
    }
  }

  // 如果没有当前音频，直接返回
  if (!currentAudio.value || !audioContext) {
    return
  }

  // 检查音频是否已经加载完成
  if (audioLoadingState.value === 'loading') {
    uni.showToast({
      title: '音频加载中，请稍候...',
      icon: 'none',
      duration: 2000
    })
    return
  }

  if (audioLoadingState.value === 'error') {
    uni.showToast({
      title: audioLoadingError.value || '音频加载失败',
      icon: 'none',
      duration: 2000
    })
    return
  }

  try {
    // 设置加载状态，但不改变播放状态
    isLoading.value = true

    // 显示播放准备状态
    uni.showLoading({
      title: '准备播放...',
      mask: false
    })

    // 开始播放
    audioContext.play()

    // 记录播放开始时间
    playStartTime.value = Date.now()

    // 设置播放超时检查，给大文件更多时间
    const playTimeout = setTimeout(() => {
      uni.hideLoading()
      if (!isPlaying.value && isLoading.value) {
        // 不立即显示失败，而是显示加载提示
        uni.showToast({
          title: '音频文件较大，正在努力加载中...',
          icon: 'none',
          duration: 3000
        })

        // 20秒后再次提示
        const midTimeout = setTimeout(() => {
          if (!isPlaying.value && isLoading.value) {
            uni.showToast({
              title: '大文件加载需要更多时间，请耐心等待...',
              icon: 'none',
              duration: 3000
            })
          }
        }, 20000) // 20秒后提示

        // 最终超时
        const extendedTimeout = setTimeout(() => {
          if (!isPlaying.value && isLoading.value) {
            isLoading.value = false // 停止加载状态
            uni.showToast({
              title: '播放启动超时，建议检查网络后重试',
              icon: 'none',
              duration: 4000
            })
          }
        }, PLAY_START_TIMEOUT - 5000) // 45秒后最终超时

        // 清理所有超时
        setTimeout(() => {
          clearTimeout(midTimeout)
          clearTimeout(extendedTimeout)
        }, PLAY_START_TIMEOUT)
      }
    }, 5000) // 初始5秒检查

    // 验证播放是否成功启动
    setTimeout(() => {
      clearTimeout(playTimeout)
      uni.hideLoading()

      // 如果状态不同步，尝试修复
      if (audioContext && isPlaying.value !== !audioContext.paused) {
        isPlaying.value = !audioContext.paused
        if (isPlaying.value) {
          isLoading.value = false // 播放成功，停止加载状态
        }
      }

      // 如果播放成功启动，显示提示
      if (isPlaying.value) {
        uni.showToast({
          title: '开始播放',
          icon: 'success',
          duration: 1000
        })
      }
    }, 2000) // 延长到2秒检查

    // 开始播放进度跟踪（备用，主要依赖音频播放器的onTimeUpdate事件）
    startPlayProgressTracking()

    // 开始状态同步检查
    startStatusSyncCheck()
  } catch (error) {
    uni.hideLoading()
    console.error('播放音频失败:', error)

    // 停止加载状态
    isLoading.value = false
    isPlaying.value = false

    // 延迟显示错误，给音频更多时间
    setTimeout(() => {
      handleAudioError(error)
    }, 1000)
  }
}

// 开始播放进度跟踪（备用机制，主要依赖onTimeUpdate事件）
function startPlayProgressTracking() {
  // 清除之前的定时器
  if (playProgressTimer) {
    clearInterval(playProgressTimer)
  }

  // 备用定时器，只在onTimeUpdate事件失效时使用
  playProgressTimer = setInterval(() => {
    if (isPlaying.value && currentAudio.value && audioContext) {
      // 检查onTimeUpdate是否正常工作
      const audioCurrentTime = Math.floor(audioContext.currentTime)

      // 如果音频播放器的时间与我们记录的时间差距太大，说明onTimeUpdate可能失效
      if (Math.abs(audioCurrentTime - currentTime.value) > 2) {
        // 使用音频播放器的实际时间
        currentTime.value = audioCurrentTime
        totalPlayTime.value = audioCurrentTime

        // 检查是否播放完成
        if (audioCurrentTime >= duration.value && duration.value > 0) {
          onAudioComplete()
        }
      }
    }
  }, 1000)
}

// 保存当前播放记录
async function saveCurrentPlayRecord(retryCount = 0) {
  if (!currentAudio.value) {
    return
  }

  const isCompleted = currentTime.value >= duration.value
  const recordData = {
    audioId: currentAudio.value.id,
    playProgress: currentTime.value,
    playDuration: totalPlayTime.value,
    isCompleted: isCompleted
  }

  try {
    const response = await saveAudioPlayRecord(recordData)

    if (response.code !== 0) {
      throw new Error(`保存失败: ${response.msg || '未知错误'}`)
    }
  } catch (error) {
    console.error('保存播放记录失败:', error)

    // 重试机制：最多重试2次
    if (retryCount < 2) {
      setTimeout(() => {
        saveCurrentPlayRecord(retryCount + 1)
      }, (retryCount + 1) * 1000)
    }
  }
}

// 音频播放完成
async function onAudioComplete() {
  if (!currentAudio.value) return

  // 保存完成记录
  await saveCurrentPlayRecord()

  // 根据播放模式处理
  switch (playMode.value) {
    case 'single':
      // 单曲循环：音频播放器会自动重新播放，我们只需要重置计时
      currentTime.value = 0
      totalPlayTime.value = 0
      playStartTime.value = Date.now()
      break
    case 'order':
      // 顺序播放：播放下一首，到最后一首就停止
      const currentIndex = filteredAudioList.value.findIndex(audio => audio.id === currentAudio.value!.id)
      if (currentIndex < filteredAudioList.value.length - 1) {
        nextTrack()
      } else {
        // 播放完最后一首，停止播放
        isPlaying.value = false
        uni.showToast({
          title: '播放完成',
          icon: 'success',
          duration: 1500
        })
      }
      break
    case 'list':
      // 列表循环：播放下一首，到最后一首后回到第一首
      nextTrack()
      break
    case 'pause':
      // 单曲暂停：播放完当前歌曲后暂停
      isPlaying.value = false
      uni.showToast({
        title: '单曲播放完成',
        icon: 'success',
        duration: 1500
      })
      break
  }
}

// 检查文本是否需要滚动
function checkTextScrolling() {
  // 简单的字符长度检测，实际项目中可以使用更精确的方法
  const maxTitleLength = 15 // 根据实际显示宽度调整
  const maxSubtitleLength = 20

  if (currentAudio.value) {
    titleNeedsScroll.value = currentAudio.value.title.length > maxTitleLength
    subtitleNeedsScroll.value = currentAudio.value.subtitle.length > maxSubtitleLength
  }
}

// 上一首
function previousTrack() {
  if (!currentAudio.value || isLoading.value) return

  const currentIndex = filteredAudioList.value.findIndex(audio => audio.id === currentAudio.value.id)
  let prevIndex = currentIndex - 1

  // 根据播放模式处理上一首逻辑
  if (playMode.value === 'order') {
    // 顺序播放：到第一首就停止
    if (prevIndex < 0) {
      uni.showToast({
        title: '已是第一首',
        icon: 'none',
        duration: 1500
      })
      return
    }
  } else {
    // 列表循环：到第一首前回到最后一首
    if (prevIndex < 0) {
      prevIndex = filteredAudioList.value.length - 1
    }
  }

  if (filteredAudioList.value[prevIndex]) {
    const wasPlaying = isPlaying.value
    // 停止当前加载状态
    isLoading.value = false
    selectAudio(filteredAudioList.value[prevIndex])
    // 如果之前在播放，则继续播放新音频
    if (wasPlaying) {
      setTimeout(() => {
        if (currentAudio.value) {
          playAudio(currentAudio.value)
        }
      }, 100)
    }
  }
}

// 下一首
function nextTrack() {
  if (!currentAudio.value || isLoading.value) return

  const currentIndex = filteredAudioList.value.findIndex(audio => audio.id === currentAudio.value.id)
  let nextIndex = currentIndex + 1

  // 根据播放模式处理下一首逻辑
  if (playMode.value === 'order') {
    // 顺序播放：到最后一首就停止
    if (nextIndex >= filteredAudioList.value.length) {
      uni.showToast({
        title: '已是最后一首',
        icon: 'none',
        duration: 1500
      })
      return
    }
  } else {
    // 列表循环：到最后一首后回到第一首
    if (nextIndex >= filteredAudioList.value.length) {
      nextIndex = 0
    }
  }

  if (filteredAudioList.value[nextIndex]) {
    const wasPlaying = isPlaying.value
    // 停止当前加载状态
    isLoading.value = false
    selectAudio(filteredAudioList.value[nextIndex])
    // 如果之前在播放，则继续播放新音频
    if (wasPlaying) {
      setTimeout(() => {
        if (currentAudio.value) {
          playAudio(currentAudio.value)
        }
      }, 100)
    }
  }
}

// 切换收藏状态
async function toggleFavorite(audioId: number) {
  try {
    const response = await toggleAudioFavorite(audioId)

    if (response.code === 0) {
      // 更新本地数据中的收藏状态
      const updateAudioFavoriteStatus = (audioList: AudioResourceRespVO[]) => {
        const audio = audioList.find(item => item.id === audioId)
        if (audio) {
          audio.isFavorited = !audio.isFavorited
        }
      }

      updateAudioFavoriteStatus(allAudioList.value)
      updateAudioFavoriteStatus(recentAudioList.value)
      updateAudioFavoriteStatus(favoriteAudioList.value)

      // 如果当前在收藏页面且取消了收藏，则从列表中移除
      if (currentCategory.value === 'favorite') {
        favoriteAudioList.value = favoriteAudioList.value.filter(item => item.id !== audioId || item.isFavorited)
      }

      const isNowFavorited = response.data

      uni.showToast({
        title: isNowFavorited ? '已收藏' : '已取消收藏',
        icon: 'success'
      })
    } else {
      console.warn('⚠️ 收藏操作失败:', response)
    }
  } catch (error) {
    console.error('收藏操作失败:', error)
    uni.showToast({
      title: '操作失败，请重试',
      icon: 'none'
    })
  }
}

// 删除音频
async function removeAudio(audioId: number) {
  // 查找要删除的音频信息
  const audioToDelete = recentAudioList.value.find(item => item.id === audioId)
  const audioSource = (audioToDelete as any)?.audioSource

  let content = '确定要从最近播放中删除这首音频吗？'
  if (currentCategory.value === 'favorite') {
    content = '确定要取消收藏这首音频吗？'
  } else if (audioSource === 'reading') {
    const bookTitle = (audioToDelete as any)?.bookTitle
    if (bookTitle) {
      content = `确定要删除这首音频吗？\n\n注意：这将同时删除《${bookTitle}》的阅读记录，删除后无法恢复。`
    } else {
      content = '确定要删除这首音频吗？\n\n注意：这将同时删除对应的阅读记录，删除后无法恢复。'
    }
  }

  uni.showModal({
    title: '确认删除',
    content: content,
    success: async (res) => {
      if (res.confirm) {
        try {
          if (currentCategory.value === 'favorite') {
            // 取消收藏
            await removeAudioFavorite(audioId)
            // 从收藏列表中移除
            favoriteAudioList.value = favoriteAudioList.value.filter(item => item.id !== audioId)
          } else if (currentCategory.value === 'recent') {
            // 对于播放记录来源的音频，删除播放记录
            if (audioSource === 'play') {
              await deleteAudioPlayRecord(audioId)
            } else if (audioSource === 'reading') {
              // 对于阅读记录来源的音频，删除对应的阅读记录
              const readingRecordId = (audioToDelete as any)?.readingRecordId
              if (readingRecordId) {
                await deleteReadingRecord(readingRecordId)
                console.log('已删除阅读记录:', readingRecordId)
              }
            }

            // 从前端列表中移除
            recentAudioList.value = recentAudioList.value.filter(item => item.id !== audioId)
          }

          // 根据删除的内容显示不同的提示
          let successMessage = '已删除'
          if (currentCategory.value === 'recent') {
            if (audioSource === 'play') {
              successMessage = '已从播放记录中删除'
            } else if (audioSource === 'reading') {
              successMessage = '已删除音频和阅读记录'
            } else {
              successMessage = '已删除（仅本次显示）'
            }
          } else if (currentCategory.value === 'favorite') {
            successMessage = '已取消收藏'
          }

          uni.showToast({
            title: successMessage,
            icon: 'success',
            duration: 2000
          })
        } catch (error) {
          console.error('删除失败:', error)
          uni.showToast({
            title: '删除失败，请重试',
            icon: 'none'
          })
        }
      }
    }
  })
}

// 切换播放模式
function togglePlayMode() {
  // 循环切换播放模式：顺序播放 → 列表循环 → 单曲循环 → 单曲暂停 → 顺序播放
  const modes: Array<'order' | 'list' | 'single' | 'pause'> = ['order', 'list', 'single', 'pause']
  const currentIndex = modes.indexOf(playMode.value)
  const nextIndex = (currentIndex + 1) % modes.length
  playMode.value = modes[nextIndex]

  // 如果有音频播放器实例，同步设置循环模式
  if (audioContext) {
    audioContext.loop = playMode.value === 'single'
  }

  // 保存到本地存储
  uni.setStorageSync('audioPlayMode', playMode.value)

  // 显示对应的提示，只显示四个字
  const modeNames = {
    order: '顺序播放',
    list: '列表循环',
    single: '单曲循环',
    pause: '单曲暂停'
  }

  uni.showToast({
    title: modeNames[playMode.value],
    icon: 'success',
    duration: 1500
  })
}

// 恢复播放模式设置
function restorePlayMode() {
  const savedMode = uni.getStorageSync('audioPlayMode')
  if (savedMode && ['order', 'list', 'single', 'pause'].includes(savedMode)) {
    playMode.value = savedMode
  }
}

// 切换定时器（打开定时器弹窗）
function toggleTimer() {
  showTimerModal.value = true
}

// 关闭定时器弹窗
function closeTimerModal() {
  showTimerModal.value = false
}

// 设置定时器
function setTimer(minutes: number) {
  audioTimerMinutes.value = minutes

  // 清除之前的定时器
  if (timerInterval.value) {
    clearInterval(timerInterval.value)
    timerInterval.value = null
  }

  if (minutes > 0) {
    // 设置新的定时器
    remainingTime.value = minutes * 60 // 转换为秒
    timerEnabled.value = true

    // 开始倒计时
    timerInterval.value = setInterval(() => {
      remainingTime.value--

      if (remainingTime.value <= 0) {
        // 时间到，停止播放
        stopPlaybackByTimer()
      }
    }, 1000)

    // 缓存到本地存储
    uni.setStorageSync('audioTimerMinutes', minutes)
    uni.setStorageSync('timerStartTime', Date.now())

    uni.showToast({
      title: `已设置${minutes}分钟后停止播放`,
      icon: 'success'
    })
  } else {
    timerEnabled.value = false
    remainingTime.value = 0
    uni.removeStorageSync('audioTimerMinutes')
    uni.removeStorageSync('timerStartTime')

    uni.showToast({
      title: '已取消定时停止',
      icon: 'success'
    })
  }
}

// 取消定时器
function cancelTimer() {
  setTimer(0)
  closeTimerModal()
}

// 定时器到时停止播放
function stopPlaybackByTimer() {
  isPlaying.value = false
  timerEnabled.value = false
  remainingTime.value = 0

  if (timerInterval.value) {
    clearInterval(timerInterval.value)
    timerInterval.value = null
  }

  // 清除缓存
  uni.removeStorageSync('audioTimerMinutes')
  uni.removeStorageSync('timerStartTime')

  uni.showToast({
    title: '播放已定时停止',
    icon: 'success'
  })
}

// 格式化倒计时显示
function formatCountdown(seconds: number): string {
  const mins = Math.floor(seconds / 60)
  const secs = seconds % 60
  return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
}

// 注意：这个函数已被parseAudioDuration替代，保留以防需要
// function parseDuration(durationStr: string): number {
//   const parts = durationStr.split(':')
//   const minutes = parseInt(parts[0]) || 0
//   const seconds = parseInt(parts[1]) || 0
//   return minutes * 60 + seconds
// }

// 恢复定时器状态
function restoreTimerState() {
  const savedMinutes = uni.getStorageSync('audioTimerMinutes')
  const startTime = uni.getStorageSync('timerStartTime')

  if (savedMinutes && startTime) {
    const elapsed = Math.floor((Date.now() - startTime) / 1000) // 已经过去的秒数
    const totalSeconds = savedMinutes * 60
    const remaining = totalSeconds - elapsed

    if (remaining > 0) {
      // 还有剩余时间，恢复定时器
      audioTimerMinutes.value = savedMinutes
      remainingTime.value = remaining
      timerEnabled.value = true

      // 重新开始倒计时
      timerInterval.value = setInterval(() => {
        remainingTime.value--

        if (remainingTime.value <= 0) {
          stopPlaybackByTimer()
        }
      }, 1000)
    } else {
      // 时间已到，清除缓存
      uni.removeStorageSync('audioTimerMinutes')
      uni.removeStorageSync('timerStartTime')
    }
  }
}

// 根据音频ID定位到对应音频
const locateAudioById = (audioId: number) => {
  try {
    // 在当前音频列表中查找对应的音频
    const targetAudio = filteredAudioList.value.find(audio => audio.id === audioId)

    if (targetAudio) {
      // 找到音频，选择但不自动播放
      selectAudio(targetAudio)

      // 显示提示
      uni.showToast({
        title: `已选择：${targetAudio.title}`,
        icon: 'none',
        duration: 2000
      })
    } else {
      // 没找到音频，可能在其他分类中，显示提示
      uni.showToast({
        title: '未找到指定音频',
        icon: 'none',
        duration: 2000
      })
    }
  } catch (error) {
    console.error('定位音频失败:', error)
  }
}

onLoad((options: any) => {
  // 初始化音频播放器
  initAudioContext()

  restoreTimerState()
  restorePlayMode() // 恢复播放模式设置
  loadCategories()
  loadAudioData()

  // 如果传入了audioId参数，尝试定位到对应音频
  if (options?.audioId) {
    const audioId = Number(options.audioId)
    if (audioId) {
      // 延迟执行，等待音频列表加载完成
      setTimeout(() => {
        locateAudioById(audioId)
      }, 1000)
    }
  }
})

onShow(() => {
  // 页面显示时刷新数据
  loadAudioData()
})

onHide(async () => {
  // 页面隐藏时保存当前播放记录
  if (currentAudio.value && isPlaying.value) {
    await saveCurrentPlayRecord()
  }
})

onUnload(async () => {
  // 保存当前播放记录
  if (currentAudio.value && isPlaying.value) {
    await saveCurrentPlayRecord()
  }

  // 清理音频播放器
  if (audioContext) {
    audioContext.stop()
    audioContext.destroy()
    audioContext = null
  }

  // 清理定时器
  if (timerInterval.value) {
    clearInterval(timerInterval.value)
    timerInterval.value = null
  }

  if (playProgressTimer) {
    clearInterval(playProgressTimer)
    playProgressTimer = null
  }

  // 停止状态同步检查
  stopStatusSyncCheck()

  // 停止音频播放
  isPlaying.value = false
  isLoading.value = false
})
</script>

<style lang="scss" scoped>
// 导入公共样式变量
@import '@/styles/variables.scss';

.audio-container {
  min-height: 100vh;
  background: $bg-gradient;
  padding: $container-padding;
  padding-bottom: 100px; // 为底部播放器留空间
}

/* 分类切换标签 - 儿童友好风格 */
.category-tabs {
  @include glass-effect;
  padding: $spacing-md;
  margin-bottom: $spacing-md;
  border-radius: $border-radius-xl;
  box-shadow: $shadow-lg;

  /* 搜索框容器 */
  .search-container {
    margin-bottom: $spacing-md;

    :deep(.wd-search) {
      .wd-search__input-wrap {
        background: rgba(255, 255, 255, 0.9);
        border-radius: $border-radius-xl;
        border: 2px solid transparent;
        transition: $transition-all;
        box-shadow: $shadow-sm;

        &:focus-within {
          border-color: $primary-blue;
          box-shadow: $shadow-blue;
          background: rgba(255, 255, 255, 1);
        }
      }

      .wd-search__input {
        font-size: $font-size-base;
        color: $dark-gray;
        font-family: $font-family;

        &::placeholder {
          color: $medium-gray;
          font-size: $font-size-base;
        }
      }

      .wd-search__icon {
        color: $primary-blue;
      }

      .wd-search__clear {
        color: $medium-gray;

        &:active {
          color: $primary-blue;
        }
      }
    }
  }

  /* 分类按钮组 */
  .tabs-wrapper {
    display: flex;

    .tab-item {
      flex: 1;
      text-align: center;
      padding: $spacing-md 0;
      border-radius: $border-radius-xl;
      margin: 0 $spacing-sm;
      background-color: $light-gray;
      transition: $transition-all;
      cursor: pointer;

      .tab-text {
        font-size: $font-size-base;
        color: $medium-gray;
        font-weight: $font-weight-medium;
        font-family: $font-family;
      }

      &.active {
        background: $blue-gradient;
        box-shadow: $shadow-blue;

        .tab-text {
          color: $white;
          font-weight: $font-weight-semibold;
        }
      }

      &:active {
        transform: scale(0.95);
      }
    }
  }
}

/* 音频列表 - 儿童友好风格 */
.audio-list {
  @include glass-effect;
  border-radius: $border-radius-xl;
  box-shadow: $shadow-lg;
  overflow: hidden;

  /* 播放全部按钮 */
  .play-all-btn {
    display: flex;
    align-items: center;
    gap: $spacing-sm;
    padding: $spacing-md $spacing-xl;
    margin: $spacing-md;
    background: $blue-gradient;
    border-radius: $border-radius-3xl;
    width: fit-content;
    box-shadow: $shadow-blue;
    transition: $transition-all;

    .play-all-text {
      font-size: $font-size-md;
      color: $white;
      font-weight: $font-weight-semibold;
      font-family: $font-family;
    }

    .audio-count {
      font-size: $font-size-base;
      color: rgba(255, 255, 255, 0.8);
      font-weight: $font-weight-medium;
    }

    &:active {
      transform: scale(0.95);
      box-shadow: $shadow-blue-lg;
    }

    &.disabled {
      opacity: 0.6;
      pointer-events: none;
    }
  }

  // 加载状态
  .loading-container {
    @include center-flex;
    flex-direction: column;
    padding: $spacing-3xl;
    gap: $spacing-lg;

    .loading-spinner {
      width: 40px;
      height: 40px;
      border: 3px solid rgba(74, 144, 226, 0.2);
      border-top: 3px solid $primary-blue;
      border-radius: 50%;
      animation: spin 1s linear infinite;
    }

    .loading-text {
      font-size: $font-size-base;
      color: $medium-gray;
      font-family: $font-family;
    }

    .retry-text {
      font-size: $font-size-sm;
      color: $primary-blue;
      font-family: $font-family;
      margin-top: $spacing-sm;
    }
  }

  // 错误状态
  .error-container {
    @include center-flex;
    flex-direction: column;
    padding: $spacing-3xl;
    gap: $spacing-lg;

    .error-icon {
      font-size: 48px;
      opacity: 0.6;
    }

    .error-text {
      font-size: $font-size-lg;
      color: $dark-gray;
      font-weight: $font-weight-medium;
      font-family: $font-family;
    }

    .error-tip {
      font-size: $font-size-base;
      color: $medium-gray;
      text-align: center;
      line-height: 1.5;
      font-family: $font-family;
    }

    .retry-btn {
      margin-top: $spacing-lg;
      padding: $spacing-md $spacing-xl;
      background: $blue-gradient;
      color: $white;
      border: none;
      border-radius: $border-radius-xl;
      font-size: $font-size-base;
      font-weight: $font-weight-medium;
      box-shadow: $shadow-blue;
      transition: $transition-all;

      &:active {
        transform: scale(0.95);
        box-shadow: $shadow-blue-lg;
      }
    }
  }



  // 空状态
  .empty-container {
    @include center-flex;
    flex-direction: column;
    padding: $spacing-3xl;
    gap: $spacing-lg;

    .empty-icon {
      font-size: 48px;
      opacity: 0.6;
    }

    .empty-text {
      font-size: $font-size-lg;
      color: $dark-gray;
      font-weight: $font-weight-medium;
      font-family: $font-family;
    }

    .empty-tip {
      font-size: $font-size-base;
      color: $medium-gray;
      text-align: center;
      line-height: 1.5;
      font-family: $font-family;
    }
  }

  @keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }

  @keyframes pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.5; }
  }

  .list-content {
    .audio-item {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: $spacing-md;
      border-bottom: 1px solid $border-color-light;
      transition: $transition-all;
      cursor: pointer;

      &.active {
        background: rgba(66, 187, 255, 0.1);
        border-left: 4px solid $primary-blue;

        .item-title {
          color: $primary-blue;
          font-weight: $font-weight-semibold;
        }
      }

      &:active {
        background-color: $light-gray;
        transform: scale(0.98);
      }

      &:last-child {
        border-bottom: none;
      }

      .item-left {
        display: flex;
        align-items: center;
        flex: 1;
        min-width: 0;

        .item-number {
          width: 16px;
          text-align: center;
          font-size: $font-size-base;
          color: $medium-gray;
          margin-right: $spacing-sm;
          font-weight: $font-weight-medium;
          font-family: $font-family;
        }

        .item-cover {
          width: 56px;
          height: 56px;
          border-radius: $border-radius-md;
          margin-right: $spacing-lg;
          box-shadow: $shadow-md;
          flex-shrink: 0;
        }

        .item-info {
          flex: 1;
          min-width: 0;

          .item-title {
            display: block;
            font-size: $font-size-md;
            color: $dark-gray;
            margin-bottom: $spacing-xs;
            font-weight: $font-weight-medium;
            font-family: $font-family;
            @include text-ellipsis;
          }

          .item-subtitle {
            display: block;
            font-size: $font-size-base;
            color: $medium-gray;
            @include text-ellipsis;
          }

          .item-source-title {
            display: block;
            font-size: $font-size-sm;
            color: $primary-blue;
            margin-top: $spacing-xs;
            @include text-ellipsis;
          }

          .loading-hint {
            display: block;
            font-size: $font-size-sm;
            color: $primary-blue;
            font-weight: $font-weight-medium;
            margin-top: $spacing-xs;
            animation: pulse 1.5s ease-in-out infinite;
          }

          .error-hint {
            display: block;
            font-size: $font-size-sm;
            color: #ff4757;
            font-weight: $font-weight-medium;
            margin-top: $spacing-xs;
          }
        }

      &.loading {
        background: rgba(66, 187, 255, 0.05);
        border-left: 4px solid rgba(66, 187, 255, 0.3);

        .item-cover {
          opacity: 0.7;
        }
      }
      }

      .item-right {
        display: flex;
        align-items: center;
        gap: $spacing-sm;
        flex-shrink: 0;

        .item-duration {
          .duration-text {
            font-size: $font-size-sm;
            color: $medium-gray;
            font-family: $font-family;
          }
        }

        .favorite-btn {
          @include center-flex;
          width: 36px;
          height: 36px;
          border-radius: $border-radius-full;
          background: rgba(255, 255, 255, 0.8);
          box-shadow: $shadow-sm;
          transition: $transition-all;

          &:active {
            transform: scale(0.9);
            box-shadow: $shadow-md;
          }
        }

        .delete-btn {
          @include center-flex;
          width: 36px;
          height: 36px;
          border-radius: $border-radius-full;
          background: rgba(255, 255, 255, 0.8);
          box-shadow: $shadow-sm;
          transition: $transition-all;

          &:active {
            transform: scale(0.9);
            box-shadow: $shadow-md;
          }
        }
      }
    }
  }
}

/* 底部播放器 - 儿童友好风格 */
.bottom-player {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  @include glass-effect(0.95);
  border-top: 1px solid $border-color-light;
  padding: $spacing-lg $spacing-xl;
  display: flex;
  flex-direction: column;
  z-index: $z-index-sticky;
  box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
  backdrop-filter: $glass-blur;

  // 音频加载状态指示器
  .loading-indicator {
    @include center-flex;
    flex-direction: column;
    padding: $spacing-md 0;
    gap: $spacing-sm;
    border-bottom: 1px solid $border-color-light;
    margin-bottom: $spacing-md;

    .loading-bar {
      width: 100%;
      height: 4px;
      background: rgba(255, 255, 255, 0.3);
      border-radius: 2px;
      overflow: hidden;

      .loading-progress {
        height: 100%;
        background: $blue-gradient;
        border-radius: 2px;
        transition: width 0.3s ease;
        box-shadow: 0 0 8px rgba(0, 123, 255, 0.3);
      }
    }

    .loading-text {
      font-size: $font-size-sm;
      color: $primary-blue;
      font-weight: $font-weight-medium;
      font-family: $font-family;
    }
  }

  // 错误状态指示器
  .error-indicator {
    @include center-flex;
    justify-content: space-between;
    padding: $spacing-md 0;
    border-bottom: 1px solid $border-color-light;
    margin-bottom: $spacing-md;

    .error-text {
      flex: 1;
      font-size: $font-size-sm;
      color: #ff4757;
      font-weight: $font-weight-medium;
      font-family: $font-family;
      margin-right: $spacing-md;
    }

    .retry-btn {
      padding: $spacing-xs $spacing-md;
      background: $blue-gradient;
      border-radius: $border-radius-md;
      box-shadow: $shadow-sm;
      transition: $transition-all;

      .retry-text {
        font-size: $font-size-sm;
        color: $white;
        font-weight: $font-weight-medium;
        font-family: $font-family;
      }

      &:active {
        transform: scale(0.95);
        box-shadow: $shadow-blue;
      }
    }
  }

  .player-info {
    display: flex;
    align-items: center;
    width: 100%;
    min-width: 0; // 允许flex子元素收缩
    margin-bottom: $spacing-md;

    .player-cover {
      width: 48px;
      height: 48px;
      border-radius: $border-radius-md;
      margin-right: $spacing-lg;
      flex-shrink: 0; // 封面不收缩
      box-shadow: $shadow-md;
    }

    .player-text {
      flex: 1;
      min-width: 0; // 允许文本区域收缩
      overflow: hidden;

      .player-title {
        display: block;
        font-size: $font-size-base;
        color: $dark-gray;
        font-weight: $font-weight-medium;
        font-family: $font-family;
        margin-bottom: $spacing-xs;
        white-space: nowrap;
        overflow: hidden;

        // 如果文本过长，添加滚动动画
        &.scrolling {
          animation: scroll-text 8s linear infinite;
        }

        // 默认显示省略号
        &:not(.scrolling) {
          text-overflow: ellipsis;
        }
      }

      .player-subtitle {
        display: block;
        font-size: $font-size-sm;
        color: $medium-gray;
        white-space: nowrap;
        overflow: hidden;

        // 如果文本过长，添加滚动动画
        &.scrolling {
          animation: scroll-text 8s linear infinite;
        }

        // 默认显示省略号
        &:not(.scrolling) {
          text-overflow: ellipsis;
        }
      }

      .player-source {
        display: block;
        font-size: $font-size-xs;
        color: $primary-blue;
        margin-top: 2px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
    }
  }

  // 播放进度区域
  .player-progress {
    width: 100%;
    margin-bottom: $spacing-md;

    .progress-container {
      display: flex;
      align-items: center;
      gap: $spacing-sm;
      width: 100%;
      min-height: 20px;

      .time-text {
        font-size: 12px;
        color: $medium-gray;
        font-weight: 500;
        width: 42px;
        text-align: center;
        font-family: 'Courier New', monospace;
        flex-shrink: 0;
      }

      .progress-bar-container {
        flex: 1;
        height: 20px;
        display: flex;
        align-items: center;
        cursor: pointer;
        padding: 4px 0;

        .progress-bar-bg {
          position: relative;
          width: 100%;
          height: 4px;
          background: rgba(255, 255, 255, 0.3);
          border-radius: 2px;
          overflow: hidden;
          flex-shrink: 0;

          .progress-bar-fill {
            height: 100%;
            background: $blue-gradient;
            border-radius: 2px;
            box-shadow: 0 0 8px rgba(0, 123, 255, 0.3);
            will-change: width;
          }

          .progress-bar-thumb {
            position: absolute;
            top: 50%;
            width: 12px;
            height: 12px;
            background: #007AFF;
            border: 2px solid #fff;
            border-radius: 50%;
            transform: translate(-50%, -50%);
            box-shadow: $shadow-md;
            z-index: 2;
          }
        }

        &:active .progress-bar-bg {
          .progress-bar-fill {
            box-shadow: 0 0 12px rgba(0, 123, 255, 0.5);
          }
        }
      }
    }
  }

  .player-controls {
    display: flex;
    align-items: center;
    gap: $spacing-sm;
    justify-content: center;
    width: 100%;

    .control-btn {
      @include center-flex;
      width: 40px;
      height: 40px;
      border-radius: $border-radius-full;
      background: rgba(255, 255, 255, 0.8);
      flex-shrink: 0; // 按钮不收缩
      transition: $transition-all;
      box-shadow: $shadow-sm;

      &.main-control {
        width: 48px;
        height: 48px;
        background: $blue-gradient;
        box-shadow: $shadow-blue;

        .loading-spinner-small {
          width: 20px;
          height: 20px;
          border: 2px solid rgba(255, 255, 255, 0.3);
          border-top: 2px solid #fff;
          border-radius: 50%;
          animation: spin 1s linear infinite;
        }
      }

      &:active {
        transform: scale(0.9);
      }
    }
  }
}

// 文本滚动动画
@keyframes scroll-text {
  0% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(0);
  }
  75% {
    transform: translateX(calc(-100% + 100px)); // 滚动到末尾，留100px显示空间
  }
  100% {
    transform: translateX(calc(-100% + 100px));
  }
}

/* 定时器弹窗 */
.timer-modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.timer-modal {
  width: 320px;
  background-color: #fff;
  border-radius: 12px;
  overflow: hidden;
  animation: modalSlideIn 0.3s ease-out;
}

@keyframes modalSlideIn {
  from {
    transform: scale(0.8);
    opacity: 0;
  }
  to {
    transform: scale(1);
    opacity: 1;
  }
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  border-bottom: 1px solid #f0f0f0;

  .modal-title {
    font-size: 18px;
    font-weight: 600;
    color: #333;
  }

  .modal-close {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background-color: #f5f5f5;

    &:active {
      background-color: #e5e5e5;
    }
  }
}

.modal-content {
  padding: 20px;

  .timer-option {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 15px 0;
    border-bottom: 1px solid #f8f8f8;
    cursor: pointer;

    &:last-child {
      border-bottom: none;
    }

    .option-text {
      font-size: 16px;
      color: #333;
    }

    .option-check {
      display: flex;
      align-items: center;
      justify-content: center;
    }

    &.active {
      .option-text {
        color: #007AFF;
        font-weight: 500;
      }
    }

    &:active {
      background-color: #f5f5f5;
    }
  }

  .timer-countdown {
    margin-top: 15px;
    padding: 12px;
    background-color: #f0f8ff;
    border-radius: 8px;
    text-align: center;

    .countdown-text {
      font-size: 16px;
      color: #007AFF;
      font-weight: 500;
    }
  }
}

.modal-footer {
  display: flex;
  padding: 20px;
  gap: 15px;
  border-top: 1px solid #f0f0f0;

  .modal-btn {
    flex: 1;
    height: 44px;
    border: none;
    border-radius: 8px;
    font-size: 16px;
    font-weight: 500;

    &.cancel-btn {
      background-color: #f5f5f5;
      color: #666;

      &:active {
        background-color: #e5e5e5;
      }
    }

    &.confirm-btn {
      background-color: #007AFF;
      color: #fff;

      &:active {
        background-color: #0056CC;
      }
    }
  }
}


</style>
